import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import org.htmlparser.util.ParserException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Parse some html and extract links by looking for the string <a
 * href="/homeinspectors/California/Fallbrook.aspx">
 * 
 * @author mkvalsvik
 * 
 */
public class HtmlLinkExtractor {
	
	private static Logger logger = LoggerFactory
			.getLogger(HtmlLinkExtractor.class.getName());
	private String appendedLinkPrefix;

	private String[] excludedLinkPrefixes = new String[] {"javascript", "http"};
	
	private File output;
	
	private int minimumLinkSlashCount = -1;
	
	private String requiredLinkPrefix = "/homeinspectors/";
	
	private String requiredLinkSuffix = ".aspx";

	public HtmlLinkExtractor(File output, String appendedLinkPrefix) {
		this.output = output;
		this.appendedLinkPrefix = appendedLinkPrefix;
	}

	private boolean excludeLink(String link) {
		for (int i = 0; i < excludedLinkPrefixes.length; i++) {
			String prefix = excludedLinkPrefixes[i];
			if (link.startsWith(prefix)) {
				return true;
			}
		}
		
		if (!link.startsWith(this.requiredLinkPrefix)) {
			return true;
		}
		
		if (!link.endsWith(this.requiredLinkSuffix)) {
			return true;
		}		
		
		if (minimumLinkSlashCount != -1) {
			int slashes = countChars(link, '/');
			if (slashes < minimumLinkSlashCount) {
				return true;
			}
		}
		
		return false;
	}
	
	private int countChars(String s, char ch) {
		int count = 0;
		for (int i = 0; i < s.length(); i++) {
			if (s.charAt(i) == ch) {
				count++;
			}
		}
		return count;
	}

	protected void parseDir(File dir, BufferedWriter writer)
			throws ParserException, IOException {

		File[] files = dir.listFiles();
		for (int i = 0; i < files.length; i++) {
			if (files[i].getName().endsWith(".html")) {
				parseFile(files[i], writer);
			}
		}
	}

	protected void parseFile(File file, BufferedWriter writer) throws IOException,
			ParserException {

		logger.debug("Parsing " + file.getAbsolutePath());

		// Read into a string
		// String content = FileUtils.readFileToString(file);
		BufferedReader reader = new BufferedReader(new FileReader(file));
		String line = reader.readLine();
		while (line != null) {
			int hrefPos = line.indexOf("href");
			if (hrefPos > 0) {
				int linkEndPos = line.substring(hrefPos).indexOf(">");
				if (linkEndPos > 0) {

					String link = line.substring(hrefPos, hrefPos + linkEndPos);

					// Walk back to end quote
					int quoteEndPos = link.lastIndexOf("\"");
					int nextTagBeginPos = link.lastIndexOf("<");
					if (nextTagBeginPos > 6 && nextTagBeginPos < quoteEndPos) {
						
						// Bad tag like this: href="/homeinspectors/Florida/New Port R                <a href="/homeinspectors/Florida/Odessa.aspx"
						quoteEndPos = nextTagBeginPos;
					}
					if (quoteEndPos > 6) {
						link = link.substring(6, quoteEndPos);
						if (!excludeLink(link)) {
							writer.write(appendedLinkPrefix + link);
							writer.newLine();
						}						
					}
				}
			}

			line = reader.readLine();
		}

	}

	public void processDir(File inputDir) {
		logger.debug("Starting..");

		BufferedWriter writer = null;
		try {
			writer = new BufferedWriter(new FileWriter(
					output));

			this.parseDir(inputDir, writer);
		} catch (IOException e1) {
			logger.error("Error", e1);
		} catch (ParserException e) {
			logger.error("Error", e);
		} finally {
			try {
				writer.close();
			} catch (IOException e) {
				// ignore
			}
		}
	}
	
	public void processFile(File inputFile) {
		logger.debug("Starting..");

		BufferedWriter writer = null;
		try {
			writer = new BufferedWriter(new FileWriter(
					output));
			this.parseFile(inputFile, writer);
		} catch (IOException e1) {
			logger.error("Error", e1);
		} catch (ParserException e) {
			logger.error("Error", e);
		} finally {
			try {
				writer.close();
			} catch (IOException e) {
				// ignore
			}
		}
	}


	public void setExcludedLinkPrefixes(String[] excludedLinkPrefixes) {
		this.excludedLinkPrefixes = excludedLinkPrefixes;
	}

	public void setRequiredLinkPrefix(String requiredLinkPrefix) {
		this.requiredLinkPrefix = requiredLinkPrefix;
	}

	public void setRequiredLinkSuffix(String requiredLinkSuffix) {
		this.requiredLinkSuffix = requiredLinkSuffix;
	}
	
	public void setMinimumLinkSlashCount(int n) {
		this.minimumLinkSlashCount = n;
	}

}
